package models

import (
	"cgs-server/helper"
	"cgs-server/server/cgs/app/models/filter"
	"errors"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"strconv"
)

type Excel struct {
}

type ExcelSheet struct {
	SheetName   string       `json:"sheetName"`
	SheetNumber int          `json:"sheetNumber"`
	Rows        ExcelRowList `json:"rows"`
}

type ExcelSheetList []*ExcelSheet
type ExcelRowList []*ExcelRow
type ExcelCellList []*ExcelCell

type ExcelRow struct {
	// 单元格信息
	Cells ExcelCellList `json:"cells" bson:"cells"`
	// 行号
	RowNumber int `json:"rowNumber" bson:"rowNumber"`
}

type ExcelCell struct {
	// 列号
	ColumnNumber int `json:"columnNumber" bson:"columnNumber"`
	// 值
	Value string `json:"value" bson:"value"`
}

type ExcelImport struct {
	Filepath    string                 `json:"filepath" bson:"-"`
	RowNumber   int                    `json:"rowNumber"`
	SheetNumber int                    `json:"sheetNumber"`
	Values      map[string]interface{} `json:"values"` // 字段没有选对应的列时，列数为nil
	WorksheetId primitive.ObjectID     `json:"worksheetId"`

	Errors  *ImportErrorList // 导入数据时的错误信息
	RowList []*WorksheetRow
}

type ImportErrorList []*ImportError

// ImportError 导入错误
type ImportError struct {
	RowNumber int    `json:"rowNumber" bson:"rowNumber"`
	ColNumber int    `json:"colNumber" bson:"colNumber"`
	ErrMsg    string `json:"errMsg" bson:"errMsg"`
}

func (e *ImportError) Sting() {
	e.ErrMsg = fmt.Sprintf("(第%d行) (第%d列) 导入数据格式错误", e.RowNumber+1, e.ColNumber+1)
}

func (ex *ExcelImport) ResolveWorksheetData(f *excelize.File, fields *Fields) ([]*WorksheetRow, error) {
	name := f.GetSheetName(ex.SheetNumber)
	rows, err := f.GetRows(name)
	if err != nil {
		return nil, err
	}
	if len(rows) == 0 || rows[ex.RowNumber] == nil {
		return nil, errors.New("worksheet is empty")
	}

	var rowList []*WorksheetRow
	var errorList = ImportErrorList{}

	for rowIndex, row := range rows {
		if rowIndex <= ex.RowNumber {
			continue
		}
		// 一条记录的数据
		rowData := RowData{}
		// 默认值都设置为 nil
		for _, field := range *fields {
			rowData[field.Name] = nil
		}

		for colIndex, colCell := range row {
			if colCell == "" {
				continue
			}
			for key, value := range ex.Values {
				if _, ok := value.(string); ok {
					continue
				}
				if v, ok := value.(float64); ok {
					if colIndex != int(v) {
						continue
					}
					dataType, options := fields.GetDataTypeAndOptions(key)
					switch dataType {
					case filter.Num:
						i, err := strconv.ParseFloat(colCell, 64)
						// 数字精度
						pre := options.Value("precision")
						if pre != nil {
							precision := int(pre.(float64))
							s := strconv.FormatFloat(i, 'f', precision, 64)
							i, err = strconv.ParseFloat(s, 64)
						}
						if err != nil {
							e := ImportError{
								RowNumber: rowIndex,
								ColNumber: colIndex,
							}
							e.Sting()
							errorList = append(errorList, &e)
							continue
						}
						rowData[key] = i
					case filter.DATE:
						if options != nil {
							format := options.Value("valueFormat").(string)
							t, err := helper.ParseExcelDateTime(colCell, format)
							if err != nil {
								return nil, err
							}
							rowData[key] = t
						} else {
							rowData[key] = colCell
						}
					case filter.NotExitType:
						// 无此字段
					default:
						rowData[key] = colCell
					}
				}
			}
		}

		// 判断是否全空
		flag := true
		for _, field := range *fields {
			if rowData[field.Name] != nil {
				if v, ok := rowData[field.Name].(string); ok {
					if v != "" {
						flag = false
						break
					}
				} else {
					flag = false
					break
				}

			}
		}
		if flag {
			// 循环下一行
			continue
		}
		rowList = append(rowList, &WorksheetRow{
			WorksheetId: ex.WorksheetId.Hex(),
			Data:        rowData,
		})
	}
	ex.Errors = &errorList
	return rowList, nil
}
